#!/usr/bin/env bash

[[ -n $DEBUG ]] && set -x
set -o errtrace         # Make sure any error trap is inherited
set -o nounset          # Disallow expansion of unset variables
set -o pipefail         # Use last non-zero exit code in a pipeline

######################################################################################################
# 软件下载路径
######################################################################################################
# 软件
YUM_REPOS="http://mirrors.aliyun.com/repo/Centos-7.repo"
#--- nodejs (setup_16.x | setup_18.x | setup_20.x)
NODEJS_URL="https://rpm.nodesource.com/setup_20.x"
#--- jdk(安装)
JDK_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-8u202-linux-x64.tar.gz"
#--- jdk8(参考)
JDK8_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-8u411-linux-x64.tar.gz"
#--- jdk11(参考)
JDK11_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-11.0.23_linux-x64_bin.tar.gz"
#--- jdk17(参考)
JDK17_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-17.0.11_linux-x64_bin.tar.gz"
#--- jdk21(参考)
JDK21_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-21.0.3_linux-x64_bin.tar.gz"
#--- gradle (6.8.3 | 6.9.4 | 7.6.3 | 8.2.1)
GRADLE_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/Gradle/gradle-6.8.3-bin.zip"
#--- maven (3.8.8 | 3.9.7)
MAVEN_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/Maven/apache-maven-3.9.7-bin.tar.gz"
#--- jenkins (http://mirrors.jenkins.io/war-stable/latest/)
JENKINS_JAVA_URL="http://all.msvc.top:30005/public/app-pkgs/raw/branch/main/OracleJDK/jdk-17.0.11_linux-x64_bin.tar.gz"
JENKINS_URL="https://ftp-nyc.osuosl.org/pub/jenkins/war-stable/latest/jenkins.war"
#--- redis Latest Stable
REDIS_URL="https://download.redis.io/redis-stable.tar.gz"

######################################################################################################
# 脚本设置
######################################################################################################
# 安装目录
INSTALL_DIR="/opt"
# 日志文件
LOG_FILE="/tmp/env-install-$(date +"%H%M%S").log"
# 安装步骤执行标记文件
SETUP_STATE_FILE="/tmp/env-install-setup.txt"
# sudo用户名密码
SUDO_TAG="0"
SUDO_USER="${SUDO_USER:-root}"
SUDO_PASSWORD="${SUDO_PASSWORD:-}"
# 执行 install 指令
INSTALL_TAG="0"
# 更新系统源
UPDATE_YUM_REPOS="0"
# 配置操作系统
CONFIG_TAG="0"
# 新增用户
ADD_USER_TAG="0"
# 新增用户
ADD_USER_NAME="www"
# 新增用户的密码
ADD_USER_PASSWORD="VdNmXpKXQ0JLYw8A0UJfWw"
# 允许新增用户ssh远程登录系统
ADD_USER_SSH_ALLOW="0"
# 安装git
GIT_TAG="0"
# 安装dstat
DSTAT_TAG="0"
# 安装htop
HTOP_TAG="0"
# 安装nginx
NGINX_TAG="0"
# 安装nodejs
NODEJS_TAG="0"
# 安装java
JAVA_TAG="0"
# 安装gradle
GRADLE_TAG="0"
# 安装maven
MAVEN_TAG="0"
# 安装jenkins
JENKINS_TAG="0"
# 安装redis
REDIS_TAG="0"
# 当前脚本文件名称(仅显示)
SCRIPT_FILE_NAME="env-install-rocky9.sh"

######################################################################################################
# 临时变量
######################################################################################################
# 存储所有命令行参数
SCRIPT_PARAMETER="$*"
# 存储命令执行返回值的的临时变量
COMMAND_OUTPUT=""
# 普通日志信息
ACCESS_INFO="\n\033[32mACCESS Summary: \033[0m\n  "
# 错误日志信息
ERROR_INFO="\n\033[31mERROR Summary: \033[0m\n  "
# 执行过程中存在错误的标识
HAS_ERROR="0"

######################################################################################################
# 通用函数
######################################################################################################

trap trap::info 1 2 3 15 EXIT

# 信号处理
function trap::info() {
    [[ ${#ERROR_INFO} -gt 37 ]] && echo -e "$ERROR_INFO"
    [[ ${#ACCESS_INFO} -gt 38 ]] && echo -e "$ACCESS_INFO"
    [ -f "$LOG_FILE" ] && echo -e "\n\n  See detailed log >>> cat $LOG_FILE \n\n"
    trap '' EXIT
    exit
}

# 错误日志
function log::error() {
    HAS_ERROR="1"
    local item; item="[$(date +'%Y-%m-%dT%H:%M:%S.%N%z')]: \033[31mERROR:   \033[0m$*"
    ERROR_INFO="${ERROR_INFO}${item}\n  "
    echo -e "${item}" | tee -a "$LOG_FILE"
}

# 基础日志
function log::info() {
    printf "[%s]: \033[32mINFO:    \033[0m%s\n" "$(date +'%Y-%m-%dT%H:%M:%S.%N%z')" "$*" | tee -a "$LOG_FILE"
}

# 警告日志
function log::warning() {
    printf "[%s]: \033[33mWARNING: \033[0m%s\n" "$(date +'%Y-%m-%dT%H:%M:%S.%N%z')" "$*" | tee -a "$LOG_FILE"
}

# 访问信息
function log::access() {
    ACCESS_INFO="${ACCESS_INFO}$*\n  "
    printf "[%s]: \033[32mINFO:    \033[0m%s\n" "$(date +'%Y-%m-%dT%H:%M:%S.%N%z')" "$*" | tee -a "$LOG_FILE"
}

# 执行日志
function log::exec() {
    printf "[%s]: \033[34mEXEC:    \033[0m%s\n" "$(date +'%Y-%m-%dT%H:%M:%S.%N%z')" "$*" >> "$LOG_FILE"
}

# 转义引号
function utils::quote() {
    # shellcheck disable=SC2046
    if [ $(echo "$*" | tr -d "\n" | wc -c) -eq 0 ]; then
        echo "''"
    elif [ $(echo "$*" | tr -d "[a-z][A-Z][0-9]:,.=~_/\n-" | wc -c) -gt 0 ]; then
        printf "%s" "$*" | sed -e "1h;2,\$H;\$!d;g" -e "s/'/\'\"\'\"\'/g" | sed -e "1h;2,\$H;\$!d;g" -e "s/^/'/g" -e "s/$/'/g"
    else
        echo "$*"
    fi
}

# 本地执行命令
function command::exec() {
    local command="$*"
    if [[ "${SUDO_TAG:-}" == "1" ]]; then
        sudo_options="sudo -H -n -u ${SUDO_USER}"
        if [[ "${SUDO_PASSWORD:-}" != "" ]]; then
            sudo_options="${sudo_options// -n/} -p \"\" -S <<< \"${SUDO_PASSWORD}\""
        fi
        command="$sudo_options bash -c $(utils::quote "$command")"
    fi
    command="$(utils::quote "$command")"
    log::exec "[command]" "bash -c $(printf "%s" "${command//${SUDO_PASSWORD:-}/zzzzzz}")"
    # shellcheck disable=SC2094
    COMMAND_OUTPUT=$(eval bash -c "${command}" 2>> "$LOG_FILE" | tee -a "$LOG_FILE")
    local status=$?
    return $status
}

# 检查返回码
function check::exit_code() {
    local code=${1:-}
    local app=${2:-}
    local desc=${3:-}
    local exit_script=${4:-}
    if [[ "${code}" == "0" ]]; then
        log::info "[${app}]" "${desc} succeeded."
    else
        log::error "[${app}]" "${desc} failed."
        [[ "$exit_script" == "exit" ]] && exit "$code"
    fi
}

# 检查命令是否存在
function check::command_exists() {
    local cmd=${1}
    local package=${2}
    if command -V "$cmd" > /dev/null 2>&1; then
        log::info "[check]" "$cmd command exists."
    else
        log::warning "[check]" "I require $cmd but it's not installed."
        log::warning "[check]" "install $package package."
        command::exec "yum install -y ${package}"
        check::exit_code "$?" "check" "$package install" "exit"
    fi
}

# 下载文件
function utils::download_file() {
    local url="$1"
    local dest="$2"
    local unzip_tag="${3:-1}"
    local dest_dirname; dest_dirname=$(dirname "$dest")
    local filename; filename=$(basename "$dest")
    log::info "[download]" "${filename}"
    command::exec "
        set -e
        if [ ! -f \"${dest}\" ]; then
            [ ! -d \"${dest_dirname}\" ] && mkdir -pv \"${dest_dirname}\"
            wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate \"${url}\" -O \"${dest}\"
            if [[ \"${unzip_tag}\" == \"unzip\" ]]; then
                command -v unzip 2>/dev/null || yum install -y unzip
                unzip -o \"${dest}\" -d \"${dest_dirname}\"
            fi
        else
            echo \"${dest} is exists!\"
        fi
    "
    local status="$?"
    check::exit_code "$status" "download" "${filename}" "exit"
    return "$status"
}

# 检查用到的命令
function check::command() {
    check::command_exists tar tar
    check::command_exists wget wget
    check::command_exists unzip gzip
}

######################################################################################################
# 安装函数
######################################################################################################

# 预检
function check::preflight() {
    # check command
    check::command
}

# 更新yum源
function init::update_yum_repos() {
    log::info "[update-yum-repos]" "更新yum源..."
    if [[ -f /etc/yum.repos.d/rocky.repo ]]; then
        sed -e 's|^mirrorlist=|#mirrorlist=|g' \
            -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
            -i.bak \
            /etc/yum.repos.d/[Rr]ocky*.repo
    fi
    command::exec "
        yum install -y epel-release
    "
    if [[ -f /etc/yum.repos.d/epel.repo ]]; then
        sed -e 's!^mirrorlist=!#mirrorlist=!g' \
            -e 's!^metalink=!#metalink=!g' \
            -e 's!^#baseurl=!baseurl=!g' \
            -e 's!//download.*/pub!//mirrors.aliyun.com!g' \
            -e 's!http://mirrors\.aliyun!https://mirrors.aliyun!g' \
            -i /etc/yum.repos.d/epel.repo
    fi
    command::exec "
        yum clean all
    "
    check::exit_code "$?" "update-yum-repos" "更新yum源" "exit"
    log::info "[update-yum-repos]" "yum源更新成功!"
}

# 配置系统
function init::config() {
    log::info "[config]" "关闭系统防火墙..."
    command::exec "
        # 停止防火墙
        systemctl stop firewalld
        # 彻底关闭防火墙
        systemctl disable firewalld
    "
    log::info "[config]" "系统防火墙关闭成功!"
}

# 新增用户
function init::add_user() {
    log::info "[add-user]" "新增用户[${ADD_USER_NAME}]..."
    local add_sudoers="${ADD_USER_NAME}    ALL=(ALL)       NOPASSWD:ALL"
    command::exec "
        id -u ${ADD_USER_NAME} >/dev/null 2>&1
        if [ \$? -ne '0' ]; then
            # 创建用户
            adduser ${ADD_USER_NAME}
            # 设置密码
            echo ${ADD_USER_NAME}:${ADD_USER_PASSWORD} | chpasswd
            # 禁止远程登录
            [[ '$ADD_USER_SSH_ALLOW' == '1' ]] && echo DenyUsers ${ADD_USER_NAME} >> /etc/ssh/sshd_config
        fi
        if [ \`grep -c '$add_sudoers' '/etc/sudoers'\` == '0' ];then
            # 新增修改权限
            chmod -v u+w /etc/sudoers
            echo -e '$add_sudoers' >> /etc/sudoers
            # 收回修改权限
            chmod -v u-w /etc/sudoers
        fi
    "
    check::exit_code "$?" "add-user" "新增用户[${ADD_USER_NAME}]" "exit"
    log::info "[add-user]" "新增用户[${ADD_USER_NAME}]成功!"
}

# 安装git环境
function install::git() {
    log::info "[git]" "安装git环境..."
    local exc_cmd="git config --global credential.helper store"
    command::exec "
        yum -y install git
        git --version
        $exc_cmd
    "
    check::exit_code "$?" "git" "安装git环境" "exit"
    log::info "[git]" "git环境安装成功!"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            echo '${ADD_USER_PASSWORD}' | su - ${ADD_USER_NAME} -c '$exc_cmd'
        "
        check::exit_code "$?" "git" "git配置" "exit"
        log::info "[git]" "git配置成功!"
    fi
}

# 安装dstat
function install::dstat() {
    log::info "[dstat]" "安装dstat..."
    command::exec "
        yum -y install dstat
        dstat -V
    "
    check::exit_code "$?" "dstat" "安装dstat" "exit"
    log::info "[dstat]" "dstat安装成功!"
}

# 安装htop
function install::htop() {
    log::info "[htop]" "安装htop..."
    command::exec "
        yum -y install htop
        htop -V
    "
    check::exit_code "$?" "htop" "安装htop" "exit"
    log::info "[htop]" "htop安装成功!"
}

# 安装nginx
function install::nginx() {
    log::info "[nginx]" "安装nginx..."
    command::exec "
        yum -y install nginx
        nginx -v
    "
    check::exit_code "$?" "nginx" "安装nginx" "exit"
    log::info "[nginx]" "nginx安装成功!"
    log::info "[nginx]" "配置文件路径: /etc/nginx"
    log::info "[nginx]" "设置开机启动: sudo systemctl enable nginx"
    log::info "[nginx]" "启动/停止/重启: sudo service nginx start/stop/restart"
    log::info "[nginx]" "检查nginx配置: sudo nginx -t"
    log::info "[nginx]" "加载nginx配置: sudo nginx -s reload"
}

# 安装nodejs环境
function install::nodejs() {
    log::info "[nodejs]" "安装nodejs环境..."
    command::exec "
        curl -fsSL ${NODEJS_URL} | sudo bash -
        yum -y install nodejs
        yum -y install npm
        npm install --global yarn
        # 配置npm源
        npm config set registry https://registry.npmmirror.com
        # 配置yarn源
        yarn config set registry https://registry.npmmirror.com -g
        # 验证
        node -v
        npm -v
        yarn -v
    "
    check::exit_code "$?" "nodejs" "安装nodejs环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            # 配置npm源
            echo '${ADD_USER_PASSWORD}' | su - ${ADD_USER_NAME} -c 'npm config set registry https://registry.npmmirror.com'
            # 配置yarn源
            echo '${ADD_USER_PASSWORD}' | su - ${ADD_USER_NAME} -c 'yarn config set registry https://registry.npmmirror.com -g'
        "
        check::exit_code "$?" "nodejs" "nodejs配置" "exit"
        log::info "[nodejs]" "nodejs配置成功!"
    fi
    log::info "[nodejs]" "安装nodejs环境成功!"
}

# 安装java环境
function install::java() {
    log::info "[java]" "安装java环境..."
    local tmp_download="tmp_download"
    local tmp_dir="tmp"
    command::exec "
        yum -y remove *openjdk*
        mkdir -p ${INSTALL_DIR}/java
        cd ${INSTALL_DIR}/java
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${JDK_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ]; then
            echo '下载失败=${JDK_URL}'
            cd ../
        else
            mkdir ./${tmp_dir}
            tar -zxvf \$file_name -C ./${tmp_dir}
            mv \$file_name ../\$file_name
            cd ./${tmp_dir}
            file_name=\`ls ./ | head -n 1\`
            mv \$file_name ../../\$file_name
            cd ../../
            line=\"\n\"
            add_profile=\`echo -e \"\${line}JAVA_HOME=${INSTALL_DIR}/java/\$file_name\${line}PATH=\\\\\$JAVA_HOME/bin:\\\\\$PATH\${line}export JAVA_HOME PATH\"\`
            echo \"\$add_profile\" >> /etc/profile
            source /etc/profile
        fi
        rm -rf ./${tmp_download}
        java -version
    "
    check::exit_code "$?" "java" "安装java环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            sudo chown -R \$(id -u ${ADD_USER_NAME}):\$(id -g ${ADD_USER_NAME}) ${INSTALL_DIR}/java
        "
    fi
    log::info "[java]" "java环境安装成功!系统环境配置: /etc/profile"
}

# 安装gradle环境
function install::gradle() {
    log::info "[gradle]" "安装gradle环境..."
    local tmp_download="tmp_download"
    local tmp_dir="tmp"
    command::exec "
        mkdir -p ${INSTALL_DIR}/gradle
        cd ${INSTALL_DIR}/gradle
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${GRADLE_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ];then
            echo '下载失败=${GRADLE_URL}'
            cd ../
        else
            mkdir ./${tmp_dir}
            unzip \$file_name -d ./${tmp_dir}
            mv \$file_name ../\$file_name
            cd ./${tmp_dir}
            file_name=\`ls ./ | head -n 1\`
            mv \$file_name ../../\$file_name
            cd ../../
            line=\"\n\"
            add_profile=\`echo -e \"\${line}GRADLE_HOME=${INSTALL_DIR}/gradle/\$file_name\${line}PATH=\\\\\$GRADLE_HOME/bin:\\\\\$PATH\${line}export GRADLE_HOME PATH\"\`
            echo \"\$add_profile\" >> /etc/profile
            source /etc/profile
        fi
        rm -rf ./${tmp_download}
        gradle -v
    "
    check::exit_code "$?" "gradle" "安装gradle环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            sudo chown -R \$(id -u ${ADD_USER_NAME}):\$(id -g ${ADD_USER_NAME}) ${INSTALL_DIR}/gradle
        "
    fi
    log::info "[gradle]" "gradle环境安装成功!系统环境配置: /etc/profile"
}

# 安装maven环境
function install::maven() {
    log::info "[maven]" "安装maven环境..."
    local tmp_download="tmp_download"
    local tmp_dir="tmp"
    command::exec "
        mkdir -p ${INSTALL_DIR}/maven
        cd ${INSTALL_DIR}/maven
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${MAVEN_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ];then
            echo '下载失败=${MAVEN_URL}'
            cd ../
        else
            mkdir ./${tmp_dir}
            tar -zxvf \$file_name -C ./${tmp_dir}
            mv \$file_name ../\$file_name
            cd ./${tmp_dir}
            file_name=\`ls ./ | head -n 1\`
            mv \$file_name ../../\$file_name
            cd ../../
            line=\"\n\"
            add_profile=\`echo -e \"\${line}MAVEN_HOME=${INSTALL_DIR}/maven/\$file_name\${line}PATH=\\\\\$MAVEN_HOME/bin:\\\\\$PATH\${line}export MAVEN_HOME PATH\"\`
            echo \"\$add_profile\" >> /etc/profile
            source /etc/profile
        fi
        rm -rf ./${tmp_download}
        mvn -v
    "
    check::exit_code "$?" "maven" "安装maven环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            sudo chown -R \$(id -u ${ADD_USER_NAME}):\$(id -g ${ADD_USER_NAME}) ${INSTALL_DIR}/maven
        "
    fi
    log::info "[maven]" "maven环境安装成功!系统环境配置: /etc/profile"
}

# 安装jenkins环境
function install::jenkins() {
    log::info "[jenkins]" "安装jenkins环境..."
    local tmp_download="tmp_download"
    local tmp_dir="tmp"
    local java_mem_opts=" -DappName=jenkins -server -Xmx1g"
    local database_opts=" -Ddatabase.codeset=ISO-8859-1 -Ddatabase.logging=false"
    local java_opts_ext=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -Duser.language=C.UTF-8"
    command::exec "
        sudo yum install -y fontconfig
        java_bin=\"\"
        jar_file=\"\"
        # 安装JRE
        mkdir -p ${INSTALL_DIR}/jenkins
        cd ${INSTALL_DIR}/jenkins
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${JENKINS_JAVA_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ];then
            echo '下载失败=${JENKINS_JAVA_URL}'
            cd ../
        else
            mkdir ./${tmp_dir}
            tar -zxvf \$file_name -C ./${tmp_dir}
            mv \$file_name ../\$file_name
            cd ./${tmp_dir}
            file_name=\`ls ./ | head -n 1\`
            mv \$file_name ../../\$file_name
            cd ../../
            java_bin=\"${INSTALL_DIR}/jenkins/\$file_name/bin/java\"
            \$file_name/bin/java -version
        fi
        rm -rf ./${tmp_download}
        # 安装 jenkins
        mkdir -p ${INSTALL_DIR}/jenkins
        cd ${INSTALL_DIR}/jenkins
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${JENKINS_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ];then
            echo '下载失败=${JENKINS_URL}'
        else
            mv \$file_name ../\$file_name
            jar_file=\"${INSTALL_DIR}/jenkins/jenkins.war\"
        fi
        cd ../
        rm -rf ./${tmp_download}
        # 生成脚本
        if [[ -n \$java_bin && -n \$jar_file ]]; then
            # 写文件start.sh文件
            cat << EOF > ${INSTALL_DIR}/jenkins/start.sh
#!/bin/bash

httpPort=\\\${1:-'30003'}

#-------------------------------------------------------------------
java='\$java_bin'
jar_file='\$jar_file'
java_mem_opts='$java_mem_opts'
database_opts='$database_opts'
java_opts_ext='$java_opts_ext'
#-------------------------------------------------------------------

pid=\\\`ps -ef | grep 'DappName=jenkins ' | grep -v 'grep' | awk '{print \\\$2}'\\\`
if [ -z \\\$pid ];then
    nohup \\\$java \\\$java_mem_opts \\\$database_opts \\\$java_opts_ext -jar \\\$jar_file --httpPort=\\\$httpPort >${INSTALL_DIR}/jenkins/logs.log 2>&1 &
    echo 'jenkins启动成功!'
else
    echo 'jenkins正在运行...'
fi
echo '查看日志:  tail -F ${INSTALL_DIR}/jenkins/logs.log -n 100'
EOF
            # 写文件kill.sh文件
            cat << EOF > ${INSTALL_DIR}/jenkins/kill.sh
#!/bin/bash

pid=\\\`ps -ef | grep 'DappName=jenkins ' | grep -v 'grep' | awk '{print \\\$2}'\\\`
if [ -z \\\$pid ];then
    echo 'jenkins未运行'
else
    ps -ef | grep 'DappName=jenkins ' | grep -v 'grep' | awk '{print \\\$2}' | xargs kill
    echo 'jenkins已停止!'
fi
EOF
            chmod +x ${INSTALL_DIR}/jenkins/start.sh
            chmod +x ${INSTALL_DIR}/jenkins/kill.sh
        fi
    "
    check::exit_code "$?" "jenkins" "安装jenkins环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            sudo chown -R \$(id -u ${ADD_USER_NAME}):\$(id -g ${ADD_USER_NAME}) ${INSTALL_DIR}/jenkins
        "
    fi
    log::info "[jenkins]" "jenkins环境安装成功!"
    log::info "[jenkins]" "启动jenkins: ${INSTALL_DIR}/jenkins/start.sh 30003"
    log::info "[jenkins]" "停止jenkins: ${INSTALL_DIR}/jenkins/kill.sh"
}

# 安装redis环境
function install::redis() {
    log::info "[redis]" "安装redis环境..."
    local tmp_download="tmp_download"
    local tmp_dir="tmp"
    command::exec "
        mkdir -p ${INSTALL_DIR}/redis
        cd ${INSTALL_DIR}/redis
        rm -rf ./${tmp_download}
        mkdir ./${tmp_download}
        cd ./${tmp_download}
        wget --timeout=10 --waitretry=3 --tries=5 --retry-connrefused --no-check-certificate ${REDIS_URL}
        file_name=\`ls ./ | head -n 1\`
        if [ -z \$file_name ]; then
            echo '下载失败=${REDIS_URL}'
            cd ../
        else
            mkdir ./${tmp_dir}
            tar -zxvf \$file_name -C ./${tmp_dir}
            mv \$file_name ../\$file_name
            cd ./${tmp_dir}
            file_name=\`ls ./ | head -n 1\`
            mv \$file_name ../../\$file_name
            cd ../../
        fi
        rm -rf ./${tmp_download}
        # 编译安装
        if [ -n \$file_name ]; then
            yum -y install gcc gcc-c++ automake autoconf libtool make
            redis_install_path=\"${INSTALL_DIR}/redis/\$file_name-install\"
            mkdir -p \$redis_install_path
            cd \$file_name
            make install PREFIX=\$redis_install_path
            # 写入配置文件
            cat << EOF > \$redis_install_path/redis.conf
# bind 127.0.0.1
protected-mode yes
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 300
daemonize yes
supervised auto
pidfile \$redis_install_path/redis.pid
loglevel notice
logfile \$redis_install_path/redis.log
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir \$redis_install_path/
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass admin123456
# 限制内存4GB = 4294967296 bytes
maxmemory 4294967296
maxmemory-policy allkeys-lfu
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800
appendonly no
appendfilename \"appendonly.aof\"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events \"\"
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes
EOF
            # 写文件start.sh文件
            cat << EOF > \$redis_install_path/start.sh
#!/bin/bash
#set -x
set -e

pid=\\\`ps -ef | grep '\$redis_install_path/bin/redis-server' | grep -v 'grep' | awk '{print \\\$2}'\\\`
cd \$redis_install_path
if [ -z \\\$pid ];then
    \$redis_install_path/bin/redis-server \$redis_install_path/redis.conf
    echo 'redis启动成功!'
else
    echo 'redis正在运行...'
fi
echo '查看日志:  tail -F \$redis_install_path/redis.log -n 100'
EOF
            # 写文件kill.sh文件
            cat << EOF > \$redis_install_path/kill.sh
#!/bin/bash
#set -x
set -e
pid=\\\`ps -ef | grep '\$redis_install_path/bin/redis-server' | grep -v 'grep' | awk '{print \\\$2}'\\\`
if [ -z \\\$pid ];then
    echo 'redis未运行'
else
    ps -ef | grep '\$redis_install_path/bin/redis-server' | grep -v 'grep' | awk '{print \\\$2}' | xargs kill
    echo 'redis已停止!'
fi
EOF
            chmod +x \$redis_install_path/start.sh
            chmod +x \$redis_install_path/kill.sh
        fi
  "
    check::exit_code "$?" "redis" "安装redis环境" "exit"
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        command::exec "
            sudo chown -R \$(id -u ${ADD_USER_NAME}):\$(id -g ${ADD_USER_NAME}) ${INSTALL_DIR}/redis
        "
    fi
    log::info "[redis]" "redis环境安装成功!"
    log::info "[redis]" "启动redis: ${INSTALL_DIR}/redis/redis-stable/start.sh"
    log::info "[redis]" "停止redis: ${INSTALL_DIR}/redis/redis-stable/kill.sh"
}

######################################################################################################
# 主调用逻辑
######################################################################################################

# 安装软件
function install() {
    # 创建安装步骤执行标记文件
    [ ! -f "${SETUP_STATE_FILE}" ] && echo "" > $SETUP_STATE_FILE
    log::info "[setup]" "setup file: $SETUP_STATE_FILE"
    # 更新yum源
    if [[ "${UPDATE_YUM_REPOS:-}" == "1" ]]; then
        if grep -q "update_yum_repos" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 update_yum_repos"
        else
            init::update_yum_repos
            echo "update_yum_repos" >> $SETUP_STATE_FILE
        fi
    fi
    # 配置系统
    if [[ "${CONFIG_TAG:-}" == "1" ]]; then
        if grep -q "config" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 config"
        else
            init::config
            echo "config" >> $SETUP_STATE_FILE
        fi
    fi
    # 新增用户
    if [[ "${ADD_USER_TAG:-}" == "1" ]]; then
        if grep -q "add_user" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 add_user"
        else
            init::add_user
            echo "add_user" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装git环境
    if [[ "${GIT_TAG:-}" == "1" ]]; then
        if grep -q "install_git" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 git"
        else
            install::git
            echo "install_git" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装dstat
    if [[ "${DSTAT_TAG:-}" == "1" ]]; then
        if grep -q "install_dstat" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 dstat"
        else
            install::dstat
            echo "install_dstat" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装htop
    if [[ "${HTOP_TAG:-}" == "1" ]]; then
        if grep -q "install_htop" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 htop"
        else
            install::htop
            echo "install_htop" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装nginx
    if [[ "${NGINX_TAG:-}" == "1" ]]; then
        if grep -q "install_nginx" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 nginx"
        else
            install::nginx
            echo "install_nginx" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装nodejs环境
    if [[ "${NODEJS_TAG:-}" == "1" ]]; then
        if grep -q "install_nodejs" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 nodejs"
        else
            install::nodejs
            echo "install_nodejs" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装java环境
    if [[ "${JAVA_TAG:-}" == "1" ]]; then
        if grep -q "install_java" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 java"
        else
            install::java
            echo "install_java" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装gradle环境
    if [[ "${GRADLE_TAG:-}" == "1" ]]; then
        if grep -q "install_gradle" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 gradle"
        else
            install::gradle
            echo "install_gradle" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装maven环境
    if [[ "${MAVEN_TAG:-}" == "1" ]]; then
        if grep -q "install_maven" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 maven"
        else
            install::maven
            echo "install_maven" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装jenkins环境
    if [[ "${JENKINS_TAG:-}" == "1" ]]; then
        if grep -q "install_jenkins" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 jenkins"
        else
            install::jenkins
            echo "install_jenkins" >> $SETUP_STATE_FILE
        fi
    fi
    # 安装redis环境
    if [[ "${REDIS_TAG:-}" == "1" ]]; then
        if grep -q "install_redis" $SETUP_STATE_FILE; then
            log::info "[skip]" "跳过已完成步骤 redis"
        else
            install::redis
            echo "install_redis" >> $SETUP_STATE_FILE
        fi
    fi
}

######################################################################################################
# main-入口
######################################################################################################

# 使用帮助
function help::usage() {
    cat << EOF
Usage:
  $SCRIPT_FILE_NAME [command]

Available Commands:
  install       安装软件
Flag:
  --update-yum-repos   是否更新yum源, 默认: '$UPDATE_YUM_REPOS'
  --config             配置系统, 默认: '$CONFIG_TAG'
  --add-user           是否新增用户, 默认: '$ADD_USER_TAG'
  --user-name          新增用户名, 默认: '$ADD_USER_NAME'
  --user-password      设置新增用密码
  --user-ssh-allow     允许新增用户ssh远程登录系统, 默认: '$ADD_USER_SSH_ALLOW'
  --base-dir           软件安装路径, 默认: '$INSTALL_DIR'
  --git                是否安装git, 默认: '$GIT_TAG'
  --dstat              是否安装dstat, 默认: '$DSTAT_TAG'
  --htop               是否安装htop, 默认: '$HTOP_TAG'
  --nginx              是否安装nginx, 默认: '$NGINX_TAG'
  --nodejs             是否安装nodejs, 默认: '$NODEJS_TAG'
  --java               是否安装java, 默认: '$JAVA_TAG'
  --gradle             是否安装gradle, 默认: '$GRADLE_TAG'
  --maven              是否安装maven, 默认: '$MAVEN_TAG'
  --jenkins            是否安装jenkins, 默认: '$JENKINS_TAG'
  --redis              是否安装redis, 默认: '$REDIS_TAG'

Example:
  [安装软件]
  $SCRIPT_FILE_NAME install \\
    --update-yum-repos 0 \\
    --config 1 \\
    --add-user 1 \\
    --user-name www \\
    --git 1 \\
    --dstat 0 \\
    --htop 0 \\
    --nginx 0 \\
    --nodejs 0 \\
    --java 1 \\
    --gradle 0 \\
    --maven 0 \\
    --jenkins 0 \\
    --redis 0

EOF
    exit 1
}

# 打印日志文件
echo -e "\033[36m tail -F $LOG_FILE -n 100 \033[0m"
# 参数处理
[ "$#" == "0" ] && help::usage
while [ "${1:-}" != "" ]; do
    case $1 in
        # -------------------------------------------------------------- 指令
        install  )              INSTALL_TAG="1"
                                ;;
        # -------------------------------------------------------------- 指令参数
        --update-yum-repos )    shift
                                UPDATE_YUM_REPOS="1"
                                ;;
        --config )              shift
                                CONFIG_TAG="1"
                                ;;
        --add-user )            shift
                                ADD_USER_TAG="1"
                                ;;
        --user-name )           shift
                                ADD_USER_NAME=${1:-$ADD_USER_NAME}
                                ;;
        --user-password )       shift
                                ADD_USER_PASSWORD=${1:-$ADD_USER_PASSWORD}
                                ;;
        --user-ssh-allow )      shift
                                ADD_USER_SSH_ALLOW="1"
                                ;;
        --base-dir )            shift
                                INSTALL_DIR="1"
                                ;;
        --git )                 shift
                                GIT_TAG="1"
                                ;;
        --dstat )               shift
                                DSTAT_TAG="1"
                                ;;
        --htop )                shift
                                HTOP_TAG="1"
                                ;;
        --nginx )               shift
                                NGINX_TAG="1"
                                ;;
        --nodejs )              shift
                                NODEJS_TAG="1"
                                ;;
        --java )                shift
                                JAVA_TAG="1"
                                ;;
        --gradle )              shift
                                GRADLE_TAG="1"
                                ;;
        --maven )               shift
                                MAVEN_TAG="1"
                                ;;
        --jenkins )             shift
                                JENKINS_TAG="1"
                                ;;
        --redis )               shift
                                REDIS_TAG="1"
                                ;;
        * )                     help::usage
                                exit 1
    esac
    shift
done

# 开始
log::info "[start]" "bash $SCRIPT_FILE_NAME ${SCRIPT_PARAMETER//${SUDO_PASSWORD:-}/zzzzzz}"
# 预检
check::preflight
# 动作
if [[ "${INSTALL_TAG:-}" == "1" ]]; then
    install
else
  help::usage
fi

# bash <(curl -s http://all.msvc.top:30005/public/helm-chart/raw/branch/master/01shell/env-install-rocky9.sh) [cmd]
# bash <(curl -s https://gitee.com/LiZhiW/helm-chart/raw/master/01shell/env-install-rocky9.sh) [cmd]
